package cn.edu.buaa.treehole.service;

import cn.edu.buaa.treehole.common.LimitPriorityHeap;
import cn.edu.buaa.treehole.dao.PostDao;
import cn.edu.buaa.treehole.dao.ReplyDao;
import cn.edu.buaa.treehole.dao.exception.DaoException;
import cn.edu.buaa.treehole.pojo.dao.ReplyDaoInfo;
import cn.edu.buaa.treehole.pojo.fixedinfo.ComparablePostInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
public class HotListService {
    private static final int listSize = 50;
    private static final int heapSize = 128;    //heapSize >= listSize * 2
    private static final int scanSize = 256;    //scanSize >= listSize
    private static final int freshPeriodHour = 1;

    private TimeService timeService;
    private final PostDao postDao;
    private final ReplyDao replyDao;

    @Autowired
    public HotListService(PostDao postDao, ReplyDao replyDao) {
        this.postDao = postDao;
        this.replyDao = replyDao;
    }

    @Autowired
    public void setTimeService(TimeService timeService) {
        this.timeService = timeService;
    }

    private List<Long> list;
    private Date freshTime;

    public Date getFreshTime() {
        return freshTime;
    }

    public List<Long> getList() throws DaoException {
        list = null;
        if (list == null || timeService.getDeltaHour(freshTime) >= freshPeriodHour) {
            System.out.println("get list fresh");
            fresh();
        }
        return list;
    }

    public boolean contain(long pid) {
        return list != null && list.contains(pid);
    }

    private void fresh() throws DaoException {
        freshTime = new Date();
        LimitPriorityHeap<ComparablePostInfo> heap = new LimitPriorityHeap<>(heapSize);
        long pid = postDao.selectMaxPid();
        System.out.println("finish get latest post id");
        FOR_LOOP:
        for (int i = 0; i < scanSize; i++) {
            while (postDao.selectAllPostByPid(pid).size() == 0) {
                pid--;
                if (pid < 0) {
                    break FOR_LOOP;
                }
            }
            int replyNum = replyDao.selectAllReplyByPid(pid).size();
            System.out.println("finish getRepliesCount " + replyNum + " " + replyDao.selectMaxRidByPid(1L));
            ReplyDaoInfo replyDaoInfo = replyDao.selectReplyById(pid, 0);
            Date createTime = replyDaoInfo.getTime();
            System.out.println("finish getPost(pid).getDate()");
            heap.enqueue(new ComparablePostInfo(pid, createTime, replyNum));
            System.out.println("finish heap.enqueue");
            pid--;
        }
        System.out.println("finish for loop");
        ArrayList<Long> newList = new ArrayList<>(listSize);
        for (int i = 0; i < listSize; i++) {
            if (heap.isEmpty()) {
                break;
            }
            newList.add(heap.dequeue().getPid());
        }
        System.out.println("finish new list add");
        list = Collections.unmodifiableList(newList);
        System.out.println("finish collection unmodifiable list");
    }
}
